using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;

namespace DslEditorPowerToy.Controls.VirtualTreeGrid.Branches
{
    /// <summary>
    /// Manages display of columns
    /// </summary>
    internal class ColumnManager
    {
        private Type _branchDataItemType = null;
        private ColumnDescriptorCollection _columnDescriptors = null;

        #region Constructors
        public ColumnManager(Type branchDataItemType)
        {
            this._branchDataItemType = branchDataItemType;
            this._columnDescriptors = new ColumnDescriptorCollection();

            PopulateStaticDescriptors();
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns count of all columns
        /// </summary>
        /// <returns></returns>
        public int GetColumnCount(BranchBase branch)
        {
            //Check if any static columns defined
            if (this._columnDescriptors.Count > 0)
                return (int)this._columnDescriptors.Count;
            else
            {
                //Calculate  number of columns from descriptors in first row (assumes each row is of same type)
                int rows = branch.VisibleItemCount;
                if (rows > 0)
                {
                    //Get the number of descriptors from first row
                    PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(branch.GetDataItem(0), null);
                    if (null != descriptors)
                        return descriptors.Count;
                }
                return 0;
            }
        }
        /// <summary>
        /// Returns the column descriptor for specified column
        /// </summary>
        /// <param name="dataItem"></param>
        /// <param name="column"></param>
        /// <returns></returns>
        public ColumnDescriptor GetDescriptorByColumn(object dataItem, int column)
        {
            //Try to get runtime descriptor for column first (by column index)
            if (null != dataItem)
            {
                PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(dataItem, null);
                if (column < descriptors.Count)
                    return new ColumnDescriptor(descriptors[column]);
            }

            //Use static decriptor
            return GetStaticDescriptorByColumn(column);
        }
        /// <summary>
        /// Gets the name of the descriptor for specified column
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public string GetDescriptorNameByColumn(int column)
        {
            return GetDescriptorNameByColumn(null, column);
        }
        /// <summary>
        /// Gets the name of the descriptor for specified column
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        public string GetDescriptorNameByColumn(object dataItem, int column)
        {
            ColumnDescriptor descriptor = GetDescriptorByColumn(dataItem, column);
            if (null == descriptor)
                return null;
            else
                return descriptor.Name;
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Returns the static propertyDescriptor of the list for specified column
        /// </summary>
        /// <param name="column"></param>
        /// <returns></returns>
        private ColumnDescriptor GetStaticDescriptorByColumn(int column)
        {
            //Check if propertyDescriptor exists for column (column is zero based)
            return this._columnDescriptors.GetByColumnOrder((int)(column + 1));
        }
        /// <summary>
        /// Populates the column descriptors collection from the static type information
        /// </summary>
        private void PopulateStaticDescriptors()
        {
            if ((null != this._branchDataItemType)
                && (typeof(object) != this._branchDataItemType))
            {
                //Create property filter for only those that are marked with the BranchColumn attribute
                Attribute[] filterAttributes = new Attribute[] { new BranchColumnAttribute() };

                //Get static reflection descriptors (sorted in alphabetic order)
                PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(this._branchDataItemType, filterAttributes);
                foreach (PropertyDescriptor descriptor in descriptors)
                    this._columnDescriptors.Add(new ColumnDescriptor(descriptor));

                //Re-sort Column descriptors (by column order)
                this._columnDescriptors.Sort();
            }
        }
        #endregion
    }
}
